package com.authine.cloudpivot.ext.controller.organization;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONArray;
import com.authine.cloudpivot.engine.api.model.organization.RoleModel;
import com.authine.cloudpivot.engine.api.model.organization.UserModel;
import com.authine.cloudpivot.ext.domain.OrgDepartment;
import com.authine.cloudpivot.ext.domain.OrgRoleUser;
import com.authine.cloudpivot.ext.domain.OrgUser;
import com.authine.cloudpivot.ext.mapper.OrgDepartmentMapper;
import com.authine.cloudpivot.ext.mapper.OrgRoleUserMapper;
import com.authine.cloudpivot.ext.mapper.OrgUserMapper;
import com.authine.cloudpivot.web.api.controller.base.BaseController;
import com.authine.cloudpivot.web.api.dubbo.DubboConfigService;
import com.authine.cloudpivot.web.api.util.ImportUtil;
import com.authine.cloudpivot.web.api.view.ResponseResult;

import cn.hutool.core.collection.CollectionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;

/**
 * Excel导入角色用户
 * 
 * @author shinka
 * @date 2021/07/04
 */
@Api(value = "Excel角色用户导入接口", tags = "01::EXTAPI::Excel导入角色用户接口")
@RestController
@RequestMapping("/public/ext/role")
public class ImportRoleUserController extends BaseController {

    private static Logger log = LoggerFactory.getLogger(ImportRoleUserController.class);

    @Resource
    private OrgUserMapper orgUserMapper;

    @Resource
    private OrgRoleUserMapper orgRoleUserMapper;

    @Resource
    private OrgDepartmentMapper orgDepartmentMapper;

    @Autowired
    private DubboConfigService dubboConfigService;

    @ApiOperation("excel导入角色用户，姓名匹配重复则匹配手机号码，手机号码也匹配不上的时候不导入这一条数据")
    @PostMapping({"/import"})
    // @Transactional(rollbackFor = Exception.class)
    public ResponseResult<Object> roleUserInsert(@RequestBody MultipartFile file) {
        log.info("excel导入角色用户开始...");
        JSONObject result = new JSONObject();
        List<String> errorResult = new ArrayList<>();
        List<String> successResult = new ArrayList<>();
        try {
            List<List<Object>> excel = excelImport(file, 0);
            List<OrgRoleUser> orgRoleUserList = new ArrayList<>();
            // 第一行为excel列标题
            for (int i = 1; i < excel.size(); i++) {
                try {
                    List<Object> cells = excel.get(i);
                    // 必填字段
                    String corpId = cells.get(5).toString();
                    String roleCode = cells.get(0).toString();
                    String userName = cells.get(2).toString();
                    // 非必填字段
                    String mobile = null;
                    Object mobileObj = cells.get(3);
                    if (null != mobileObj) {
                        mobile = mobileObj.toString();
                    }
                    String deptNames = null;
                    Object deptNamesObj = cells.get(4);
                    if (null != deptNamesObj) {
                        deptNames = deptNamesObj.toString();
                    }

                    log.info("开始导入，第" + i + "行：{corpId:{},roleCode:{},userName:{},mobile:{},deptNames:{}}", corpId,
                        roleCode, userName, mobile, deptNames);

                    OrgRoleUser orgRoleUser = new OrgRoleUser();
                    orgRoleUser.setId(UUID.randomUUID().toString().replaceAll("-", ""));
                    orgRoleUser.setCreatedTime(new Date());
                    orgRoleUser.setDeleted(false);
                    orgRoleUser.setModifiedTime(orgRoleUser.getCreatedTime());
                    orgRoleUser.setUnitType("USER");

                    // 校验用户并获取用户id
                    String userId = null;
                    List<OrgUser> orgUserList = orgUserMapper.selectByNameAndCorpId(userName, corpId);
                    if (CollectionUtil.isNotEmpty(orgUserList)) {
                        if (orgUserList.size() > 1) {
                            final String str = "[" + userName + "]: 用户在组织架构有重复, corpId=" + corpId;
                            log.info(str);
                            errorResult.add(str);
                            break;
                        } else {
                            userId = orgUserList.get(0).getId();
                        }
                    } else {
                        if (!StringUtils.isEmpty(mobile)) {
                            UserModel userModel =
                                dubboConfigService.getOrganizationFacade().getUserByMobileAndCorpId(mobile, corpId);
                            if (null != userModel) {
                                userId = userModel.getId();
                            } else {
                                final String str = "[" + userName + "]: 姓名重复，根据手机号码未匹配到用户, corpId=" + corpId;
                                log.info(str);
                                errorResult.add(str);
                                break;
                            }
                        } else {
                            final String str = "[" + userName + "]: 用户不在组织架构, corpId=" + corpId;
                            log.info(str);
                            errorResult.add(str);
                            break;
                        }
                    }
                    orgRoleUser.setUserId(userId);

                    // 获取管理范围的部门ID
                    JSONArray ouScopeArray = new JSONArray();
                    deptNames = deptNames.replace("，", ",");
                    String[] deptArr = deptNames.split(",");
                    for (String deptName : deptArr) {
                        deptName = deptName.trim();
                        log.debug("查询管理范围部门开始，部门名称={}", deptName);
                        OrgDepartment orgDept = orgDepartmentMapper.selectDeptByName(deptName);
                        if (null == orgDept) {
                            final String str = "[" + userName + "]: 管理范围部门：[{" + deptName + "}]不存在, corpId=" + corpId;
                            log.info(str);
                            errorResult.add(str);
                            break;
                        }
                        ouScopeArray.add(orgDept.getId());
                    }
                    orgRoleUser.setOuScope(ouScopeArray.toJSONString());

                    // 根据角色编码获取角色ID
                    RoleModel roleModel = dubboConfigService.getOrganizationFacade().getRoleByCode(roleCode);
                    orgRoleUser.setRoleId(roleModel.getId());

                    orgRoleUserList.add(orgRoleUser);
                    successResult.add("[" + userName + "]: " + userId);
                } catch (Exception e) {
                    final String str = "excel导入角色用户失败，第" + i + "行，exception=" + e.toString();
                    log.error(str);
                    errorResult.add(str);
                }
            }
            result.put("error", errorResult);
            result.put("success", new ArrayList<>());
            // insert db
            if (CollectionUtils.isNotEmpty(orgRoleUserList)) {
                Integer count = orgRoleUserMapper.insertByRoleUserList(orgRoleUserList);
                log.info("excel导入角色用户成功，insert count={}", count);
                result.put("success", successResult);
            }
            // 返回成功与失败的数据
            return getOkResponseResult(result, "角色用户导入完成");
        } catch (Exception e) {
            log.error("excel导入角色用户失败，exception={}", e.toString());
            return getErrResponseResult(null, null, "导入角色用户失败，exception=" + e.toString());
        }
    }

    /**
     * excel导入
     *
     * @param file
     * @param sheetNumber
     *            获取第几个sheet的值，从0开始
     * @return
     * @throws IOException
     */
    private List<List<Object>> excelImport(MultipartFile file, Integer sheetNumber) throws IOException {
        ImportUtil importUtil = new ImportUtil();
        List<List<Object>> listob;
        if (file.isEmpty()) {
            throw new IOException("Excel不存在!");
        }
        try {
            InputStream in = file.getInputStream();
            listob = importUtil.getBankListByExcel(in, file.getOriginalFilename(), sheetNumber);
            in.close();
            return listob;
        } catch (Exception e) {
            throw new IOException("Excel导入失败!");
        }
    }

}
